import { ElFormItem, ElInput, ElOption, ElSelect } from 'element-plus';
import { FieldDefine } from '@/components/bpmn-process-designer/components/dynamic-binder';
import { PropertiesMap, GroupProperties } from './index';
import SubList from '../../components/sublist/SubList';
import { SubListState } from '@/components/bpmn-process-designer/components/sublist/type';
import { ModdleElement } from '../type';
import { BpmnStore } from '../store';

/**
 * 所有通用节点的属性（每个节点都有的）
 */
const commonProperties: PropertiesMap<FieldDefine> = {
  id: {
    component: ElInput,
    disabled: true,
    placeholder: '节点ID',
    vSlots: {
      prepend: (): JSX.Element => <div>节点ID</div>
    },
    setValue(sourceObject: ModdleElement, key: string, value: string) {
      const isNotNull = value;
      const latestValue = value || ' ';
      const shape = BpmnStore.getShape();
      BpmnStore.updateProperties(shape, {
        [key]: isNotNull ? latestValue.trim() : latestValue
      });
    }
  },
  name: {
    component: ElInput,
    // prefix: '节点名称',
    placeholder: '节点名称',
    vSlots: {
      prepend: (): JSX.Element => <div>节点名称</div>
    }
  }
};

/**
 * （基础信息）每个节点都有的
 */
export const CommonGroupProperties: GroupProperties = {
  name: '基础信息',
  icon: 'el-icon-info',
  properties: { ...commonProperties }
};

interface Documentation {
  text: string;
}

export const DocumentGroupProperties: GroupProperties = {
  name: '元素文档',
  icon: 'el-icon-document',
  properties: {
    'documentation.text': {
      component: ElInput,
      type: 'textarea',
      getValue: (obj: { documentation: Array<Documentation> }): string => {
        return obj['documentation']?.[0]?.['text'] ?? '';
      },
      setValue(
        businessObject: ModdleElement,
        key: string,
        value: unknown
      ): void {
        BpmnStore.createElement(
          'bpmn:Documentation',
          'documentation',
          { text: value },
          true
        );
      }
    }
  }
};

interface PropertyElement {
  $type: string;
  name: string;
  value: unknown;
}

/**
 * 流程事件类型选项
 */
const EVENT_OPTIONS = [
  { label: 'start', value: 'start' },
  { label: 'end', value: 'end' },
  { label: 'take', value: 'take' }
];

/**
 * 监听器类型选项
 */
const TYPE_OPTIONS = [
  { label: 'java类', value: 'class' },
  { label: '调用表达式', value: 'expression' },
  { label: '注入表达式', value: 'delegateExpression' }
];

/**
 * 获取节点类型的监听器属性配置组
 * @param options 参数
 */
import { TaskNameMapping } from './TypeNameMapping';
import ApprovalConfiguration from '@/components/bpmn-process-designer/components/approval-configuration';
import { isNull, isUndefined } from 'lodash-es';
import FormConfiguration from '@/components/bpmn-process-designer/components/form-configuration';
import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import isTools from '@/utils/isTools';
import { useBpmnData } from '@/store/modules/bpmnData';
import TaskMonitor from '@/components/bpmn-process-designer/components/task-monitor';

const bpmnData = useBpmnData();

const taskTags = Object.keys(TaskNameMapping);

// 全局监听器
export const getElementTypeListenerProperties = function (options: {
  name: string;
  icon?: string;
  //时间类型选项
  eventOptions?: Array<{ label: string; value: string }>;
}): GroupProperties {
  const eventOptions = options.eventOptions || EVENT_OPTIONS;
  return {
    name: options.name || '监听器',
    icon: options.icon || 'el-icon-bell',
    properties: {
      'extensionElements.listeners': {
        component: TaskMonitor,
        title: '全局执行监听器',
        columns: [
          {
            type: 'index',
            label: '序号',
            align: 'center'
          },
          {
            prop: 'event',
            label: '事件',
            align: 'center',
            formatter: (row: any, column: any): string => {
              return EVENT_OPTIONS.filter(
                (item) => item.value === row[column.property]
              )[0].label;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.event}>
                    {eventOptions.map((option) => {
                      return (
                        <ElOption
                          key={option.value}
                          label={option.label}
                          value={option.value}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          },
          {
            prop: 'delegateExpression',
            label: '监听器',
            align: 'center',
            formatter: (row: any, column: any) => {
              return bpmnData.taskExecuteMonitor.filter(
                (item) => item.executionContent === row[column.property]
              )[0].listenerName;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.delegateExpression}>
                    {bpmnData.taskExecuteMonitor.map((option) => {
                      return (
                        <ElOption
                          key={option.listenerId}
                          label={option.listenerName}
                          value={option.executionContent}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          }
        ],
        rules: {
          event: [{ required: true, message: '事件不能为空' }],
          delegateExpression: [{ required: true, message: '监听器不能为空' }]
        },
        getValue: (businessObject: ModdleElement): Array<any> => {
          const listenerTagName = taskTags?.includes(businessObject.$type)
            ? 'flowable:TaskListener'
            : 'flowable:ExecutionListener';
          const listeners = businessObject?.extensionElements?.values?.filter(
            (item: ModdleElement) => item.$type === 'flowable:ExecutionListener'
          );
          return listeners
            ? listeners?.map((item: ModdleElement) => {
                return {
                  delegateExpression: item.delegateExpression,
                  event: item.event
                };
              })
            : [];
        },
        setValue(businessObject: ModdleElement, key: string, value: []): void {
          const bpmnContext = BpmnStore;
          const moddle = bpmnContext.getModeler().get('moddle');
          // 判断当前活动的模型类型，使用不同类型的标签监听器

          const stringModdle = moddle.create(`flowable:string`, {
            value: listenersJson
          });

          const fieldModdle = moddle.create(`flowable:Field`, {
            string: stringModdle,
            name: 'httpConfig'
          });

          bpmnContext.updateExtensionElements(
            'flowable:ExecutionListener',
            value.map((attr: { event: string; delegateExpression: string }) => {
              return moddle.create('flowable:ExecutionListener', {
                delegateExpression: attr.delegateExpression,
                event: attr.event,
                fields: [fieldModdle]
              });
            })
          );
        }
      }
    }
  };
};
/*const listenersJson = `<![CDATA[
                      {
                        "method": "POST",
                        "path":"http://localhost:19200/demo",
                        "header":：[{"key":"content-type","value": "application/json"}],
                        "body":[{"key":"name","value":"admin"}]
                      }
                    ]]>`*/
const listenersJson = `<![CDATA[
                      {
                        "method": "GET",
                        "path":"http://192.168.3.210:19200/demo/get?name=123&age=123"
                        }
                    ]]>`;
// 监听器属性
export const getElementTaskMonitorListenerProperties = function (options: {
  name: string;
  icon?: string;
  //时间类型选项
  eventOptions?: Array<{ label: string; value: string }>;
}): GroupProperties {
  const eventOptions = options.eventOptions || EVENT_OPTIONS;
  return {
    name: options.name || '监听器',
    icon: options.icon || 'el-icon-bell',
    properties: {
      'extensionElements.executeListeners': {
        component: TaskMonitor,
        title: '执行监听器',
        columns: [
          {
            type: 'index',
            label: '序号',
            align: 'center'
          },
          {
            prop: 'event',
            label: '事件',
            align: 'center',
            formatter: (row: any, column: any): string => {
              return EVENT_OPTIONS.filter(
                (item) => item.value === row[column.property]
              )[0].label;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.event}>
                    {EVENT_OPTIONS.map((option) => {
                      return (
                        <ElOption
                          key={option.value}
                          label={option.label}
                          value={option.value}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          },
          {
            prop: 'delegateExpression',
            label: '监听器',
            align: 'center',
            formatter: (row: any, column: any) => {
              return bpmnData.taskExecuteMonitor.filter(
                (item) => item.executionContent === row[column.property]
              )[0].listenerName;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.delegateExpression}>
                    {bpmnData.taskExecuteMonitor.map((option) => {
                      return (
                        <ElOption
                          key={option.listenerId}
                          label={option.listenerName}
                          value={option.executionContent}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          }
        ],
        rules: {
          event: [{ required: true, message: '事件不能为空' }],
          delegateExpression: [{ required: true, message: '监听器不能为空' }]
        },
        getValue: (businessObject: ModdleElement): Array<any> => {
          const listenerTagName = taskTags?.includes(businessObject.$type)
            ? 'flowable:TaskListener'
            : 'flowable:ExecutionListener';
          const listeners = businessObject?.extensionElements?.values?.filter(
            (item: ModdleElement) => item.$type === 'flowable:ExecutionListener'
          );
          return listeners
            ? listeners?.map((item: ModdleElement) => {
                return {
                  delegateExpression: item.delegateExpression,
                  event: item.event
                };
              })
            : [];
        },
        setValue(businessObject: ModdleElement, key: string, value: []): void {
          const bpmnContext = BpmnStore;
          const moddle = bpmnContext.getModeler().get('moddle');
          // 判断当前活动的模型类型，使用不同类型的标签监听器

          const stringModdle = moddle.create(`flowable:string`, {
            value: listenersJson
          });

          const fieldModdle = moddle.create(`flowable:Field`, {
            string: stringModdle,
            name: 'httpConfig'
          });

          bpmnContext.updateExtensionElements(
            'flowable:ExecutionListener',
            value.map((attr: { event: string; delegateExpression: string }) => {
              return moddle.create('flowable:ExecutionListener', {
                delegateExpression: attr.delegateExpression,
                event: attr.event,
                fields: [fieldModdle]
              });
            })
          );
        }
      },
      'extensionElements.listeners': {
        component: TaskMonitor,
        columns: [
          {
            type: 'index',
            label: '序号',
            align: 'center'
          },
          {
            prop: 'event',
            label: '事件',
            align: 'center',
            formatter: (row: any, column: any): string => {
              return eventOptions.filter(
                (item) => item.value === row[column.property]
              )[0].label;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.event}>
                    {eventOptions.map((option) => {
                      return (
                        <ElOption
                          key={option.value}
                          label={option.label}
                          value={option.value}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          },
          {
            prop: 'delegateExpression',
            label: '监听器',
            align: 'center',
            formatter: (row: any, column: any) => {
              return bpmnData.taskMonitor.filter(
                (item) => item.executionContent === row[column.property]
              )[0].listenerName;
            },
            editComponent: function (
              scope: any,
              state: SubListState<any>
            ): JSX.Element {
              return (
                <ElFormItem
                  size="small"
                  class="sublist-form-item"
                  label={scope.column.name}
                  prop={scope.column.property}
                >
                  <ElSelect v-model={state.editItem.delegateExpression}>
                    {bpmnData.taskMonitor.map((option) => {
                      return (
                        <ElOption
                          key={option.listenerId}
                          label={option.listenerName}
                          value={option.executionContent}
                        />
                      );
                    })}
                  </ElSelect>
                </ElFormItem>
              );
            }
          }
        ],
        rules: {
          event: [{ required: true, message: '事件不能为空' }],
          delegateExpression: [{ required: true, message: '监听器不能为空' }]
        },
        getValue: (businessObject: ModdleElement): Array<any> => {
          const listeners = businessObject?.extensionElements?.values?.filter(
            (item: ModdleElement) => item.$type === 'flowable:TaskListener'
          );
          return listeners
            ? listeners?.map((item: ModdleElement) => {
                return {
                  delegateExpression: item.delegateExpression,
                  event: item.event
                };
              })
            : [];
        },
        setValue(businessObject: ModdleElement, key: string, value: []): void {
          const bpmnContext = BpmnStore;
          const moddle = bpmnContext.getModeler().get('moddle');

          const stringModdle = moddle.create(`flowable:string`, {
            value: listenersJson
          });

          const fieldModdle = moddle.create(`flowable:Field`, {
            string: stringModdle,
            name: 'httpConfig'
          });

          bpmnContext.updateExtensionElements(
            'flowable:TaskListener',
            value.map((attr: { event: string; delegateExpression: string }) => {
              return moddle.create('flowable:TaskListener', {
                delegateExpression: attr.delegateExpression,
                event: attr.event,
                fields: [fieldModdle]
              });
            })
          );
        }
      }
    }
  };
};

/**
 * 扩展属性组配置
 */
export const ExtensionGroupProperties: GroupProperties = {
  name: '扩展属性',
  icon: 'el-icon-document-add',
  properties: {
    'extensionElements.properties': {
      component: SubList,
      columns: [
        {
          type: 'index',
          label: '序号',
          align: 'center'
        },
        {
          prop: 'name',
          label: '属性名',
          align: 'center'
        },
        {
          prop: 'value',
          label: '属性值',
          align: 'center'
        }
      ],
      rules: {
        name: [{ required: true, message: '属性名不能为空' }],
        value: [{ required: true, message: '属性值不能为空' }]
      },
      getValue: (businessObject: ModdleElement): Array<any> => {
        const extProperties = businessObject?.extensionElements?.values?.filter(
          (item: PropertyElement) => item.$type === 'flowable:Properties'
        )[0]?.values;
        return extProperties
          ? extProperties.map((item: PropertyElement) => ({
              name: item.name,
              value: item.value
            }))
          : [];
      },
      setValue(businessObject: ModdleElement, key: string, value: []): void {
        const bpmnContext = BpmnStore;
        const moddle = bpmnContext.getModeler().get('moddle');
        const properties = moddle.create(`flowable:Properties`, {
          values: value.map((attr: { name: string; value: unknown }) => {
            return moddle.create(`flowable:Property`, {
              name: attr.name,
              value: attr.value
            });
          })
        });
        bpmnContext.updateExtensionElements('flowable:Property', properties);
      }
    }
  }
};

/**
 * 自定义属性
 */
export const CustomAttribute: GroupProperties = {
  name: '自定义属性',
  icon: 'el-icon-document-add',
  properties: {
    'extensionElements.properties': {
      component: ApprovalConfiguration,
      getValue: (businessObject: ModdleElement) => {
        const bpmnContext = BpmnStore;
        const moddle = bpmnContext.getModeler().get('moddle');
        // 获取当前节点
        const node = getBusinessObject(businessObject);

        let skipExpressionType = node.skipExpression;

        if (isTools.isNull(skipExpressionType)) {
          skipExpressionType = '${false}';
          node.skipExpression = skipExpressionType;
        }

        const incomingFlows = businessObject.incoming || [];

        const returnableTaskNode = incomingFlows
          .map((flow) => flow.sourceRef)
          .filter((node) => node.$type === 'bpmn:UserTask');

        bpmnData.nodeShow = returnableTaskNode.length > 0;
        bpmnData.skipNode = skipExpressionType;

        const id = businessObject?.extensionElements?.values?.filter(
          (item: PropertyElement) => {
            return item.$type === 'flowable:RejectReturnTaskId';
          }
        )[0]?.value;

        let type = businessObject?.extensionElements?.values?.filter(
          (item: PropertyElement) => {
            return item.$type === 'flowable:RejectHandlerType';
          }
        )[0]?.value;

        if (isNull(type) || isUndefined(type)) {
          type = 1;
          const typeModdle = moddle.create(`flowable:RejectHandlerType`, {
            value: 1
          });
          bpmnContext.updateExtensionElements(
            'flowable:RejectHandlerType',
            typeModdle
          );

          const idModdle = moddle.create(`flowable:RejectReturnTaskId`, {
            value: null
          });

          bpmnContext.updateExtensionElements(
            'flowable:RejectReturnTaskId',
            idModdle
          );
        }

        return {
          userId: type === 1 ? null : id,
          type: type,
          returnableTaskNode,
          skipExpressionType
        };
      },
      setValue(businessObject: ModdleElement, key: string, value): void {
        const bpmnContext = BpmnStore;
        const moddle = bpmnContext.getModeler().get('moddle');

        // 获取当前节点
        const node = getBusinessObject(businessObject);

        node.skipExpression = value.skipExpressionType;
        bpmnData.skipNode = value.skipExpressionType;

        const userId = moddle.create(`flowable:RejectReturnTaskId`, {
          value: value.userId
        });
        const type = moddle.create(`flowable:RejectHandlerType`, {
          value: value.type
        });
        bpmnContext.updateExtensionElements(
          'flowable:RejectReturnTaskId',
          userId
        );
        bpmnContext.updateExtensionElements('flowable:RejectHandlerType', type);
      }
    }
  }
};

interface FromPropertyElement {
  $type: string;
  id: string;
  type: string;
  $attrs: FromPropertyAttrsElement;
}

interface FromPropertyAttrsElement {
  name: string;
}

/**
 * （基础信息）表单
 */
export const FormGroupProperties: GroupProperties = {
  name: '表单信息',
  icon: 'el-icon-edit',
  properties: {
    formKey: {
      component: FormConfiguration,
      placeholder: '表单key',
      getValue: (businessObject: ModdleElement) => {
        const bpmnContext = BpmnStore;
        const moddle = bpmnContext.getModeler().get('moddle');
        const formKeyProperty = businessObject.formKey;

        return {
          formKey: formKeyProperty ?? null
        };
      },
      setValue(businessObject: ModdleElement, key: string, value): void {
        const bpmnContext = BpmnStore;
        const moddle = bpmnContext.getModeler().get('moddle');
        // 获取当前节点，并为当前节点设置formKey
        const node = getBusinessObject(businessObject);
        node.formKey = value.formKey;
      },
      vSlots: {
        prepend: (): JSX.Element => <div>表单key</div>
      }
    }
  }
};
